#include "StdAfx.h"
#include "deadZ80.h"

static unsigned char parity[256] = {
	4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4,
	0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0,
	0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0,
	4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4,
	0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0,
	4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4,
	4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4,
	0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0,
	0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0,
	4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4,
	4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4,
	0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0,
	4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4,
	0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0,
	0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0,
	4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4,
};

#define A regs->af.byte.a
#define F regs->af.byte.f
#define B regs->bc.byte.b
#define C regs->bc.byte.c
#define D regs->de.byte.d
#define E regs->de.byte.e
#define H regs->hl.byte.h
#define L regs->hl.byte.l
#define AF regs->af.word
#define BC regs->bc.word
#define DE regs->de.word
#define HL regs->hl.word

#define FLAG_C	0x01
#define FLAG_N	0x02
#define FLAG_P	0x04
#define FLAG_V	FLAG_P
#define FLAG_X	0x08
#define FLAG_H	0x10
#define FLAG_Y	0x20
#define FLAG_Z	0x40
#define FLAG_S	0x80


#define setH()		F |= FLAG_H;

#define checkSZ(v)					\
	if((v) == 0)					\
		F |= FLAG_Z;			\
	if((v) & 0x80)					\
		F |= FLAG_S;

#define checkP(v)		\
	F &= ~FLAG_P;	\
	F |= parity[v];

#define checkC(v)		\
	F &= ~FLAG_C;	\
	if((v) >= 0x100)	\
		F |= FLAG_C;

#define checkV(v1,v2,r)	\
	F |= ((((v1) ^ (r)) & ((v2) ^ (r))) & 0x80) >> 5;

#define checkV16(v1,v2,r)	\
	F |= ((((v1) ^ (r)) & ((v2) ^ (r))) & 0x8000) >> (5 + 8);

#define checkSZ16(v)				\
	if((v) == 0)					\
		F |= FLAG_Z;			\
	if((v) & 0x8000)				\
		F |= FLAG_S;

#define checkHV16(v1,v2,r)				\
	if((((v1) & 0xFFF) + ((v2) & 0xFFF)) >= 0x1000)		\
		F |= FLAG_H;				\
	checkV16(v1,v2,r);

#define checkC16(v)			\
	if((v) >= 0x10000)		\
		F |= FLAG_C;

//some opcode helper macros
#define ADD(v)					\
	stmp = A + v;			\
	F &= ~(FLAG_S | FLAG_Z | FLAG_C | FLAG_V | FLAG_N | FLAG_H);			\
	F = stmp & 0x28;	\
	checkSZ(stmp & 0xFF);		\
	checkC(stmp);				\
	checkV(A,v,stmp);		\
	if(((A & 0xF) + (v & 0xF)) >= 0x10)	\
		F |= FLAG_H;		\
	A = stmp;

#define ADC(v)					\
	stmp = A + v + (F & 1);	\
	F &= ~(FLAG_S | FLAG_Z | FLAG_C | FLAG_V | FLAG_N | FLAG_H);			\
	checkSZ(stmp & 0xFF);		\
	checkC(stmp);				\
	checkV(A,v,stmp);		\
	if(((A & 0xF) + (v & 0xF)) >= 0x10)	\
		F |= FLAG_H;		\
	A = stmp;

#define AND(v)		\
	A &= v;			\
	F = A & 0x28;	\
	setH();			\
	checkSZ(A);		\
	checkP(A);

#define XOR(v)		\
	A ^= v;			\
	F = A & 0x28;	\
	checkSZ(A);		\
	checkP(A);

#define OR(v)		\
	A |= v;			\
	F = A & 0x28;	\
	checkSZ(A);		\
	checkP(A);

#define DEC(r)							\
	stmp = r - 1;						\
	F &= ~(FLAG_S | FLAG_Z | FLAG_V | FLAG_H | 0x28);	\
	F |= FLAG_N | (stmp & 0x28);		\
	checkSZ(stmp & 0xFF);				\
	checkV(stmp,1,r);					\
	if((r & 0xF) < (1 & 0xF))			\
		F |= FLAG_H;				\
	r = stmp;

#define INC(r)	\
	stmp = r + 1;			\
	F &= ~(FLAG_S | FLAG_Z | FLAG_V | FLAG_N | FLAG_H | 0x28);	\
	F |= stmp & 0x28;		\
	checkSZ(stmp & 0xFF);	\
	checkV(r,1,stmp);		\
	if(((r & 0xF) + (1 & 0xF)) >= 0x10)	\
		F |= FLAG_H;		\
	r = stmp;

#define CP(n)	\
	stmp = A - n;				\
	F &= ~(FLAG_S | FLAG_Z | FLAG_C | FLAG_V | FLAG_N | FLAG_H);	\
	F = (n & 0x28) | FLAG_N;				\
	checkSZ(stmp & 0xFF);			\
	checkC(stmp);					\
	checkV(stmp,n,A);			\
	if((A & 0xF) < (n & 0xF))		\
		F |= FLAG_H;

//#define BIT(b,r)			\
	tmp = (1 << b) & r;		\
	F &= FLAG_C;		\
	F |= FLAG_H | (r & 0x28);	\
	checkSZ(tmp);	\
	checkP(tmp);

#define BIT(b,r)		\
	tmp = (1 << b) & r;	\
	F = (F & FLAG_C) | FLAG_H;	\
	F |= (r) & 0x28;	\
	if((b == 7) && (r & 0x80))	\
		F |= FLAG_S;	\
	if(r == 0)			\
		F |= FLAG_P | FLAG_Z;

#define SET(b,r)			\
	tmp = (1 << b) | r;

#define RES(b,r)			\
	tmp = r & ~(1 << b);

#define SUB(n)						\
	tmp = n;						\
	stmp = A - tmp;					\
	F &= ~(FLAG_S | FLAG_Z | FLAG_C | FLAG_V | FLAG_H | 0x28);	\
	F |= stmp & 0x28;	\
	checkSZ(stmp & 0xFF);			\
	checkC(stmp);					\
	checkV(stmp,tmp,A);				\
	if((A & 0xF) < (tmp & 0xF))		\
		F |= FLAG_H;				\
	A = stmp;						\
	F |= FLAG_N;

#define RET(c)			\
	if(c) {				\
		pc = ReadMemory8(sp+0) | (ReadMemory8(sp+1) << 8);	\
		sp += 2;		\
		cycles += 10;	\
	}					\
	else				\
		cycles += 7;

#define RST(v)		\
	WriteMemory8(--sp,(pc >> 8) & 0xFF);	\
	WriteMemory8(--sp,(pc >> 0) & 0xFF);	\
	pc = v;			\
	cycles += 13;

#define JP(r)	\
	pc = r;	\
	cycles += 10;

#define JR(c)	\
	stmp = ReadMemory16(pc);	\
	pc += 2;	\
	if(c) {		\
		pc = stmp;		\
		cycles += 15;	\
	}		\
	else	\
		cycles += 10;

#define CALL(c)		\
	if(c) {			\
		stmp = pc + 2;	\
		WriteMemory8(--sp,(stmp >> 8) & 0xFF);		\
		WriteMemory8(--sp,stmp & 0xFF);				\
		pc = ReadMemory16(pc);	\
		cycles += 17;			\
	}		\
	else {	\
		pc += 2;		\
		cycles += 12;	\
	}

#define DEC16(r)	\
	r--;

#define INC16(r)	\
	r++;

#define ADD16(a1,a2)	\
	ltmp = a1 + a2;				\
	F &= ~(FLAG_C | FLAG_N | FLAG_H | 0x28);	\
	F |= (ltmp >> 8) & 0x28;					\
	checkC16(ltmp);								\
	if(((a1 & 0xFFF) + (a2 & 0xFFF)) >= 0x1000)	\
		F |= FLAG_H;					\
	a1 = ltmp;					\
	cycles += 7;

#define PUSH(v)	\
	WriteMemory8(--sp,v)

#define POP()	\
	ReadMemory8(sp++)

#define PUSH16(rr)	\
	WriteMemory8(--sp,((rr) >> 8) & 0xFF);	\
	WriteMemory8(--sp,(rr) & 0xFF);

#define POP16(rr)	\
	rr = ReadMemory16(sp);	\
	sp += 2;

#define EXX()	\
	utmp[0] = regs->bc.word;	\
	utmp[1] = regs->de.word;	\
	utmp[2] = regs->hl.word;	\
	regs->bc.word = alt.bc.word;	\
	regs->de.word = alt.de.word;	\
	regs->hl.word = alt.hl.word;	\
	alt.bc.word = utmp[0];	\
	alt.de.word = utmp[1];	\
	alt.hl.word = utmp[2];	\
	cycles += 4;

#define EX(r1,r2)	\
	stmp = r1;		\
	r1 = r2;		\
	r2 = stmp;		\
	cycles += 4;

#define RLC(d)						\
	d = (d << 1) | (d >> 7);		\
	F = (d & FLAG_C) | (d & 0x28);	\
	checkSZ(d);						\
	checkP(d);

#define RRC(d)					\
	F = d & FLAG_C;				\
	d = (d >> 1) | (d << 7);	\
	F |= d & 0x28;				\
	checkSZ(d);					\
	checkP(d);
	
//stolen directly from mame's z80.c
#define DAA {													\
	unsigned char cf, nf, hf, lo, hi, diff;						\
	cf = F & FLAG_C;											\
	nf = F & FLAG_N;											\
	hf = F & FLAG_H;											\
	lo = A & 15;												\
	hi = A / 16;												\
																\
	if (cf)														\
	{															\
		diff = (lo <= 9 && !hf) ? 0x60 : 0x66;					\
	}															\
	else														\
	{															\
		if (lo >= 10)											\
		{														\
			diff = hi <= 8 ? 0x06 : 0x66;						\
		}														\
		else													\
		{														\
			if (hi >= 10)										\
			{													\
				diff = hf ? 0x66 : 0x60;						\
			}													\
			else												\
			{													\
				diff = hf ? 0x06 : 0x00;						\
			}													\
		}														\
	}															\
	if (nf) A -= diff;											\
	else A += diff;												\
																\
	F &= ~FLAG_N;												\
	checkSZ(A);													\
	checkP(A);													\
	if (cf || (lo <= 9 ? hi >= 10 : hi >= 9)) F |= FLAG_C;		\
	if (nf ? hf && lo <= 5 : lo >= 10)	F |= FLAG_H;			\
}

//special opcodes for the indexed stuff
#define BIT_IDX(b)	\
	ltmp = (unsigned int)(unsigned short)((signed short)ix + (signed char)data);	\
	tmp = ReadMemory8(ltmp);	\
	BIT(b,tmp);					\
	F &= ~0x28;					\
	F |= (ltmp >> 8) & 0x28;	\
	cycles += 19;

#define SET_IDX(b)	\
	ltmp = (unsigned int)(unsigned short)((signed short)ix + (signed char)data);	\
	tmp = ReadMemory8(ltmp);	\
	SET(b,tmp);					\
	WriteMemory8(ltmp,tmp);		\
	cycles += 19;

#define RES_IDX(b)	\
	ltmp = (unsigned int)(unsigned short)((signed short)ix + (signed char)data);	\
	tmp = ReadMemory8(ltmp);	\
	RES(b,tmp);					\
	WriteMemory8(ltmp,tmp);		\
	cycles += 19;



int CDeadZ80::ExecuteOpcodeDDCB()
{
	unsigned char data = ReadMemory8(pc++);
	unsigned char opcode = ReadMemory8(pc++);
	unsigned short stmp,tmp16;
	unsigned char tmp;
	unsigned long ltmp;

	switch(opcode) {
		case 0x40:
		case 0x41:
		case 0x42:
		case 0x43:
		case 0x44:
		case 0x45:
		case 0x46:	//bit 0,(ix+n)
		case 0x47:	BIT_IDX(0);							break;
		case 0x48:
		case 0x49:
		case 0x4A:
		case 0x4B:
		case 0x4C:
		case 0x4D:
		case 0x4E:	//bit 1,(ix+n)
		case 0x4F:	BIT_IDX(1);							break;
		case 0x50:
		case 0x51:
		case 0x52:
		case 0x53:
		case 0x54:
		case 0x55:
		case 0x56:	//bit 2,(ix+n)
		case 0x57:	BIT_IDX(2);							break;
		case 0x58:
		case 0x59:
		case 0x5A:
		case 0x5B:
		case 0x5C:
		case 0x5D:
		case 0x5E:	//bit 3,(ix+n)
		case 0x5F:	BIT_IDX(3);							break;
		case 0x60:
		case 0x61:
		case 0x62:
		case 0x63:
		case 0x64:
		case 0x65:
		case 0x66:	//bit 4,(ix+n)
		case 0x67:	BIT_IDX(4);							break;
		case 0x68:
		case 0x69:
		case 0x6A:
		case 0x6B:
		case 0x6C:
		case 0x6D:
		case 0x6E:	//bit 5,(ix+n)
		case 0x6F:	BIT_IDX(5);							break;
		case 0x70:
		case 0x71:
		case 0x72:
		case 0x73:
		case 0x74:
		case 0x75:
		case 0x76:	//bit 6,(ix+n)
		case 0x77:	BIT_IDX(6);							break;
		case 0x78:
		case 0x79:
		case 0x7A:
		case 0x7B:
		case 0x7C:
		case 0x7D:
		case 0x7E:	//bit 7,(ix+n)
		case 0x7F:	BIT_IDX(7);							break;
		case 0x80:
		case 0x81:
		case 0x82:
		case 0x83:
		case 0x84:
		case 0x85:
		case 0x86:	//res 0,(ix+n)
		case 0x87:	RES_IDX(0);							break;
		case 0x88:
		case 0x89:
		case 0x8A:
		case 0x8B:
		case 0x8C:
		case 0x8D:
		case 0x8E:	//res 1,(ix+n)
		case 0x8F:	RES_IDX(1);							break;
		case 0x90:
		case 0x91:
		case 0x92:
		case 0x93:
		case 0x94:
		case 0x95:
		case 0x96:	//res 2,(ix+n)
		case 0x97:	RES_IDX(2);							break;
		case 0x98:
		case 0x99:
		case 0x9A:
		case 0x9B:
		case 0x9C:
		case 0x9D:
		case 0x9E:	//res 3,(ix+n)
		case 0x9F:	RES_IDX(3);							break;
		case 0xA0:
		case 0xA1:
		case 0xA2:
		case 0xA3:
		case 0xA4:
		case 0xA5:
		case 0xA6:	//res 4,(ix+n)
		case 0xA7:	RES_IDX(4);							break;
		case 0xA8:
		case 0xA9:
		case 0xAA:
		case 0xAB:
		case 0xAC:
		case 0xAD:
		case 0xAE:	//res 5,(ix+n)
		case 0xAF:	RES_IDX(5);							break;
		case 0xB0:
		case 0xB1:
		case 0xB2:
		case 0xB3:
		case 0xB4:
		case 0xB5:
		case 0xB6:	//res 6,(ix+n)
		case 0xB7:	RES_IDX(6);							break;
		case 0xB8:
		case 0xB9:
		case 0xBA:
		case 0xBB:
		case 0xBC:
		case 0xBD:
		case 0xBE:	//res 7,(ix+n)
		case 0xBF:	RES_IDX(7);							break;
		case 0xC0:
		case 0xC1:
		case 0xC2:
		case 0xC3:
		case 0xC4:
		case 0xC5:
		case 0xC6:	//set 0,(ix+n)
		case 0xC7:	SET_IDX(0);							break;
		case 0xC8:
		case 0xC9:
		case 0xCA:
		case 0xCB:
		case 0xCC:
		case 0xCD:
		case 0xCE:	//set 1,(ix+n)
		case 0xCF:	SET_IDX(1);							break;
		case 0xD0:
		case 0xD1:
		case 0xD2:
		case 0xD3:
		case 0xD4:
		case 0xD5:
		case 0xD6:	//set 2,(ix+n)
		case 0xD7:	SET_IDX(2);							break;
		case 0xD8:
		case 0xD9:
		case 0xDA:
		case 0xDB:
		case 0xDC:
		case 0xDD:
		case 0xDE:	//set 3,(ix+n)
		case 0xDF:	SET_IDX(3);							break;
		case 0xE0:
		case 0xE1:
		case 0xE2:
		case 0xE3:
		case 0xE4:
		case 0xE5:
		case 0xE6:	//set 4,(ix+n)
		case 0xE7:	SET_IDX(4);							break;
		case 0xE8:
		case 0xE9:
		case 0xEA:
		case 0xEB:
		case 0xEC:
		case 0xED:
		case 0xEE:	//set 5,(ix+n)
		case 0xEF:	SET_IDX(5);							break;
		case 0xF0:
		case 0xF1:
		case 0xF2:
		case 0xF3:
		case 0xF4:
		case 0xF5:
		case 0xF6:	//set 6,(ix+n)
		case 0xF7:	SET_IDX(6);							break;
		case 0xF8:
		case 0xF9:
		case 0xFA:
		case 0xFB:
		case 0xFC:
		case 0xFD:
		case 0xFE:	//set 7,(ix+n)
		case 0xFF:	SET_IDX(7);							break;

		default:
			printf("bad DDCB opcode = $%02X\n",opcode);
			return(1);
	}
	return(0);
}

int CDeadZ80::ExecuteOpcodeCB()
{
	unsigned char opcode = ReadMemory8(pc++);
	unsigned short stmp,tmp16;
	unsigned char tmp;
	unsigned long ltmp;

	switch(opcode) {

		case 0x06:	tmp = ReadMemory8(HL);	RLC(tmp);	WriteMemory8(HL,tmp);	cycles += 14;	break;
		case 0x0E:	tmp = ReadMemory8(HL);	RRC(tmp);	WriteMemory8(HL,tmp);	cycles += 14;	break;

		case 0x40:	BIT(0,B);	cycles += 4;	break;
		case 0x41:	BIT(0,C);	cycles += 4;	break;
		case 0x42:	BIT(0,D);	cycles += 4;	break;
		case 0x43:	BIT(0,E);	cycles += 4;	break;
		case 0x44:	BIT(0,H);	cycles += 4;	break;
		case 0x45:	BIT(0,L);	cycles += 4;	break;
		case 0x46:	tmp = ReadMemory8(HL);	BIT(0,tmp);	cycles += 4;	break;
		case 0x47:	BIT(0,A);	cycles += 4;	break;
		case 0x48:	BIT(1,B);	cycles += 4;	break;
		case 0x49:	BIT(1,C);	cycles += 4;	break;
		case 0x4A:	BIT(1,D);	cycles += 4;	break;
		case 0x4B:	BIT(1,E);	cycles += 4;	break;
		case 0x4C:	BIT(1,H);	cycles += 4;	break;
		case 0x4D:	BIT(1,L);	cycles += 4;	break;
		case 0x4E:	tmp = ReadMemory8(HL);	BIT(1,tmp);	cycles += 4;	break;
		case 0x4F:	BIT(1,A);	cycles += 4;	break;
		case 0x50:	BIT(2,B);	cycles += 4;	break;
		case 0x51:	BIT(2,C);	cycles += 4;	break;
		case 0x52:	BIT(2,D);	cycles += 4;	break;
		case 0x53:	BIT(2,E);	cycles += 4;	break;
		case 0x54:	BIT(2,H);	cycles += 4;	break;
		case 0x55:	BIT(2,L);	cycles += 4;	break;
		case 0x56:	tmp = ReadMemory8(HL);	BIT(2,tmp);	cycles += 4;	break;
		case 0x57:	BIT(2,A);	cycles += 4;	break;
		case 0x58:	BIT(3,B);	cycles += 4;	break;
		case 0x59:	BIT(3,C);	cycles += 4;	break;
		case 0x5A:	BIT(3,D);	cycles += 4;	break;
		case 0x5B:	BIT(3,E);	cycles += 4;	break;
		case 0x5C:	BIT(3,H);	cycles += 4;	break;
		case 0x5D:	BIT(3,L);	cycles += 4;	break;
		case 0x5E:	tmp = ReadMemory8(HL);	BIT(3,tmp);	cycles += 4;	break;
		case 0x5F:	BIT(3,A);	cycles += 4;	break;
		case 0x60:	BIT(4,B);	cycles += 4;	break;
		case 0x61:	BIT(4,C);	cycles += 4;	break;
		case 0x62:	BIT(4,D);	cycles += 4;	break;
		case 0x63:	BIT(4,E);	cycles += 4;	break;
		case 0x64:	BIT(4,H);	cycles += 4;	break;
		case 0x65:	BIT(4,L);	cycles += 4;	break;
		case 0x66:	tmp = ReadMemory8(HL);	BIT(4,tmp);	cycles += 4;	break;
		case 0x67:	BIT(4,A);	cycles += 4;	break;
		case 0x68:	BIT(5,B);	cycles += 4;	break;
		case 0x69:	BIT(5,C);	cycles += 4;	break;
		case 0x6A:	BIT(5,D);	cycles += 4;	break;
		case 0x6B:	BIT(5,E);	cycles += 4;	break;
		case 0x6C:	BIT(5,H);	cycles += 4;	break;
		case 0x6D:	BIT(5,L);	cycles += 4;	break;
		case 0x6E:	tmp = ReadMemory8(HL);	BIT(5,tmp);	cycles += 4;	break;
		case 0x6F:	BIT(5,A);	cycles += 4;	break;
		case 0x70:	BIT(6,B);	cycles += 4;	break;
		case 0x71:	BIT(6,C);	cycles += 4;	break;
		case 0x72:	BIT(6,D);	cycles += 4;	break;
		case 0x73:	BIT(6,E);	cycles += 4;	break;
		case 0x74:	BIT(6,H);	cycles += 4;	break;
		case 0x75:	BIT(6,L);	cycles += 4;	break;
		case 0x76:	tmp = ReadMemory8(HL);	BIT(6,tmp);	cycles += 4;	break;
		case 0x77:	BIT(6,A);	cycles += 4;	break;
		case 0x78:	BIT(7,B);	cycles += 4;	break;
		case 0x79:	BIT(7,C);	cycles += 4;	break;
		case 0x7A:	BIT(7,D);	cycles += 4;	break;
		case 0x7B:	BIT(7,E);	cycles += 4;	break;
		case 0x7C:	BIT(7,H);	cycles += 4;	break;
		case 0x7D:	BIT(7,L);	cycles += 4;	break;
		case 0x7E:	tmp = ReadMemory8(HL);	BIT(7,tmp);	cycles += 4;	break;
		case 0x7F:	BIT(7,A);	cycles += 4;	break;
		case 0x80:	RES(0,B);	cycles += 4;	break;
		case 0x81:	RES(0,C);	cycles += 4;	break;
		case 0x82:	RES(0,D);	cycles += 4;	break;
		case 0x83:	RES(0,E);	cycles += 4;	break;
		case 0x84:	RES(0,H);	cycles += 4;	break;
		case 0x85:	RES(0,L);	cycles += 4;	break;
		case 0x86:	tmp = ReadMemory8(HL);	RES(0,tmp);	WriteMemory8(HL,tmp);	cycles += 4;	break;
		case 0x87:	RES(0,A);	cycles += 4;	break;
		case 0x88:	RES(1,B);	cycles += 4;	break;
		case 0x89:	RES(1,C);	cycles += 4;	break;
		case 0x8A:	RES(1,D);	cycles += 4;	break;
		case 0x8B:	RES(1,E);	cycles += 4;	break;
		case 0x8C:	RES(1,H);	cycles += 4;	break;
		case 0x8D:	RES(1,L);	cycles += 4;	break;
		case 0x8E:	tmp = ReadMemory8(HL);	RES(1,tmp);	WriteMemory8(HL,tmp);	cycles += 4;	break;
		case 0x8F:	RES(1,A);	cycles += 4;	break;
		case 0x90:	RES(2,B);	cycles += 4;	break;
		case 0x91:	RES(2,C);	cycles += 4;	break;
		case 0x92:	RES(2,D);	cycles += 4;	break;
		case 0x93:	RES(2,E);	cycles += 4;	break;
		case 0x94:	RES(2,H);	cycles += 4;	break;
		case 0x95:	RES(2,L);	cycles += 4;	break;
		case 0x96:	tmp = ReadMemory8(HL);	RES(2,tmp);	WriteMemory8(HL,tmp);	cycles += 4;	break;
		case 0x97:	RES(2,A);	cycles += 4;	break;
		case 0x98:	RES(3,B);	cycles += 4;	break;
		case 0x99:	RES(3,C);	cycles += 4;	break;
		case 0x9A:	RES(3,D);	cycles += 4;	break;
		case 0x9B:	RES(3,E);	cycles += 4;	break;
		case 0x9C:	RES(3,H);	cycles += 4;	break;
		case 0x9D:	RES(3,L);	cycles += 4;	break;
		case 0x9E:	tmp = ReadMemory8(HL);	RES(3,tmp);	WriteMemory8(HL,tmp);	cycles += 4;	break;
		case 0x9F:	RES(3,A);	cycles += 4;	break;
		case 0xA0:	RES(4,B);	cycles += 4;	break;
		case 0xA1:	RES(4,C);	cycles += 4;	break;
		case 0xA2:	RES(4,D);	cycles += 4;	break;
		case 0xA3:	RES(4,E);	cycles += 4;	break;
		case 0xA4:	RES(4,H);	cycles += 4;	break;
		case 0xA5:	RES(4,L);	cycles += 4;	break;
		case 0xA6:	tmp = ReadMemory8(HL);	RES(4,tmp);	WriteMemory8(HL,tmp);	cycles += 4;	break;
		case 0xA7:	RES(4,A);	cycles += 4;	break;
		case 0xA8:	RES(5,B);	cycles += 4;	break;
		case 0xA9:	RES(5,C);	cycles += 4;	break;
		case 0xAA:	RES(5,D);	cycles += 4;	break;
		case 0xAB:	RES(5,E);	cycles += 4;	break;
		case 0xAC:	RES(5,H);	cycles += 4;	break;
		case 0xAD:	RES(5,L);	cycles += 4;	break;
		case 0xAE:	tmp = ReadMemory8(HL);	RES(5,tmp);	WriteMemory8(HL,tmp);	cycles += 4;	break;
		case 0xAF:	RES(5,A);	cycles += 4;	break;
		case 0xB0:	RES(6,B);	cycles += 4;	break;
		case 0xB1:	RES(6,C);	cycles += 4;	break;
		case 0xB2:	RES(6,D);	cycles += 4;	break;
		case 0xB3:	RES(6,E);	cycles += 4;	break;
		case 0xB4:	RES(6,H);	cycles += 4;	break;
		case 0xB5:	RES(6,L);	cycles += 4;	break;
		case 0xB6:	tmp = ReadMemory8(HL);	RES(6,tmp);	WriteMemory8(HL,tmp);	cycles += 4;	break;
		case 0xB7:	RES(6,A);	cycles += 4;	break;
		case 0xB8:	RES(7,B);	cycles += 4;	break;
		case 0xB9:	RES(7,C);	cycles += 4;	break;
		case 0xBA:	RES(7,D);	cycles += 4;	break;
		case 0xBB:	RES(7,E);	cycles += 4;	break;
		case 0xBC:	RES(7,H);	cycles += 4;	break;
		case 0xBD:	RES(7,L);	cycles += 4;	break;
		case 0xBE:	tmp = ReadMemory8(HL);	RES(7,tmp);	WriteMemory8(HL,tmp);	cycles += 4;	break;
		case 0xBF:	RES(7,A);	cycles += 4;	break;
		case 0xC0:	SET(0,B);	cycles += 4;	break;
		case 0xC1:	SET(0,C);	cycles += 4;	break;
		case 0xC2:	SET(0,D);	cycles += 4;	break;
		case 0xC3:	SET(0,E);	cycles += 4;	break;
		case 0xC4:	SET(0,H);	cycles += 4;	break;
		case 0xC5:	SET(0,L);	cycles += 4;	break;
		case 0xC6:	tmp = ReadMemory8(HL);	SET(0,tmp);	WriteMemory8(HL,tmp);	cycles += 4;	break;
		case 0xC7:	SET(0,A);	cycles += 4;	break;
		case 0xC8:	SET(1,B);	cycles += 4;	break;
		case 0xC9:	SET(1,C);	cycles += 4;	break;
		case 0xCA:	SET(1,D);	cycles += 4;	break;
		case 0xCB:	SET(1,E);	cycles += 4;	break;
		case 0xCC:	SET(1,H);	cycles += 4;	break;
		case 0xCD:	SET(1,L);	cycles += 4;	break;
		case 0xCE:	tmp = ReadMemory8(HL);	SET(1,tmp);	WriteMemory8(HL,tmp);	cycles += 4;	break;
		case 0xCF:	SET(1,A);	cycles += 4;	break;
		case 0xD0:	SET(2,B);	cycles += 4;	break;
		case 0xD1:	SET(2,C);	cycles += 4;	break;
		case 0xD2:	SET(2,D);	cycles += 4;	break;
		case 0xD3:	SET(2,E);	cycles += 4;	break;
		case 0xD4:	SET(2,H);	cycles += 4;	break;
		case 0xD5:	SET(2,L);	cycles += 4;	break;
		case 0xD6:	tmp = ReadMemory8(HL);	SET(2,tmp);	WriteMemory8(HL,tmp);	cycles += 4;	break;
		case 0xD7:	SET(2,A);	cycles += 4;	break;
		case 0xD8:	SET(3,B);	cycles += 4;	break;
		case 0xD9:	SET(3,C);	cycles += 4;	break;
		case 0xDA:	SET(3,D);	cycles += 4;	break;
		case 0xDB:	SET(3,E);	cycles += 4;	break;
		case 0xDC:	SET(3,H);	cycles += 4;	break;
		case 0xDD:	SET(3,L);	cycles += 4;	break;
		case 0xDE:	tmp = ReadMemory8(HL);	SET(3,tmp);	WriteMemory8(HL,tmp);	cycles += 4;	break;
		case 0xDF:	SET(3,A);	cycles += 4;	break;
		case 0xE0:	SET(4,B);	cycles += 4;	break;
		case 0xE1:	SET(4,C);	cycles += 4;	break;
		case 0xE2:	SET(4,D);	cycles += 4;	break;
		case 0xE3:	SET(4,E);	cycles += 4;	break;
		case 0xE4:	SET(4,H);	cycles += 4;	break;
		case 0xE5:	SET(4,L);	cycles += 4;	break;
		case 0xE6:	tmp = ReadMemory8(HL);	SET(4,tmp);	WriteMemory8(HL,tmp);	cycles += 4;	break;
		case 0xE7:	SET(4,A);	cycles += 4;	break;
		case 0xE8:	SET(5,B);	cycles += 4;	break;
		case 0xE9:	SET(5,C);	cycles += 4;	break;
		case 0xEA:	SET(5,D);	cycles += 4;	break;
		case 0xEB:	SET(5,E);	cycles += 4;	break;
		case 0xEC:	SET(5,H);	cycles += 4;	break;
		case 0xED:	SET(5,L);	cycles += 4;	break;
		case 0xEE:	tmp = ReadMemory8(HL);	SET(5,tmp);	WriteMemory8(HL,tmp);	cycles += 4;	break;
		case 0xEF:	SET(5,A);	cycles += 4;	break;
		case 0xF0:	SET(6,B);	cycles += 4;	break;
		case 0xF1:	SET(6,C);	cycles += 4;	break;
		case 0xF2:	SET(6,D);	cycles += 4;	break;
		case 0xF3:	SET(6,E);	cycles += 4;	break;
		case 0xF4:	SET(6,H);	cycles += 4;	break;
		case 0xF5:	SET(6,L);	cycles += 4;	break;
		case 0xF6:	tmp = ReadMemory8(HL);	SET(6,tmp);	WriteMemory8(HL,tmp);	cycles += 4;	break;
		case 0xF7:	SET(6,A);	cycles += 4;	break;
		case 0xF8:	SET(7,B);	cycles += 4;	break;
		case 0xF9:	SET(7,C);	cycles += 4;	break;
		case 0xFA:	SET(7,D);	cycles += 4;	break;
		case 0xFB:	SET(7,E);	cycles += 4;	break;
		case 0xFC:	SET(7,H);	cycles += 4;	break;
		case 0xFD:	SET(7,L);	cycles += 4;	break;
		case 0xFE:	tmp = ReadMemory8(HL);	SET(7,tmp);	WriteMemory8(HL,tmp);	cycles += 4;	break;
		case 0xFF:	SET(7,A);	cycles += 4;	break;
		default:
			printf("bad CB opcode $%02X\n",opcode);
			return(1);
	}
	return(0);
}

int CDeadZ80::ExecuteOpcodeDD()
{
	unsigned char opcode = ReadMemory8(pc++);
	unsigned short stmp,tmp16;
	unsigned char tmp;
	unsigned long ltmp;

	switch(opcode) {
		case 0x09:	ADD16(ix,BC);				cycles += 7;	break;
		case 0x19:	ADD16(ix,DE);				cycles += 7;	break;

		case 0x21:	//ld ix,nn
			ix = ReadMemory16(pc);
			pc += 2;
			cycles += 14;
			break;
		case 0x22:	//ld (nn),ix
			WriteMemory16(ReadMemory16(pc),ix);
			pc += 2;
			cycles += 14;
			break;
		case 0x23:	//inc ix
			ix++;
			cycles += 10;
			break;

		case 0x2A:	//ld ix,(nn)
			ix = ReadMemory16(ReadMemory16(pc));
			pc += 2;
			cycles += 14;
			break;

		case 0x34:	//inc (ix+d)
			ltmp = (unsigned long)(unsigned short)((signed short)ix + (signed char)ReadMemory8(pc++));
			tmp = ReadMemory8(ltmp);
			INC(tmp);
			WriteMemory8(ltmp,tmp);
			cycles += 19;
			break;

		case 0x35:	//dec (ix+d)
			ltmp = (unsigned long)(unsigned short)((signed short)ix + (signed char)ReadMemory8(pc++));
			tmp = ReadMemory8(ltmp);
			DEC(tmp);
			WriteMemory8(ltmp,tmp);
			cycles += 19;
			break;

		case 0x36:	//ld (ix+d),n
			ltmp = (unsigned long)(unsigned short)((signed short)ix + (signed char)ReadMemory8(pc++));
			WriteMemory8(ltmp,ReadMemory8(pc++));
			cycles += 19;
			break;

		case 0x46:	//ld b,(ix+d)
			ltmp = (unsigned long)(unsigned short)((signed short)ix + (signed char)ReadMemory8(pc++));
			B = ReadMemory8(ltmp);
			cycles += 19;
			break;
		case 0x4E:	//ld c,(ix+d)
			ltmp = (unsigned long)(unsigned short)((signed short)ix + (signed char)ReadMemory8(pc++));
			C = ReadMemory8(ltmp);
			cycles += 19;
			break;
		case 0x56:	//ld d,(ix+d)
			ltmp = (unsigned long)(unsigned short)((signed short)ix + (signed char)ReadMemory8(pc++));
			D = ReadMemory8(ltmp);
			cycles += 19;
			break;
		case 0x5E:	//ld e,(ix+d)
			ltmp = (unsigned long)(unsigned short)((signed short)ix + (signed char)ReadMemory8(pc++));
			E = ReadMemory8(ltmp);
			cycles += 19;
			break;
		case 0x66:	//ld h,(ix+d)
			ltmp = (unsigned long)(unsigned short)((signed short)ix + (signed char)ReadMemory8(pc++));
			H = ReadMemory8(ltmp);
			cycles += 19;
			break;
		case 0x6E:	//ld l,(ix+d)
			ltmp = (unsigned long)(unsigned short)((signed short)ix + (signed char)ReadMemory8(pc++));
			L = ReadMemory8(ltmp);
			cycles += 19;
			break;
		case 0x70:	//ld (ix+d),b
			ltmp = (unsigned long)(unsigned short)((signed short)ix + (signed char)ReadMemory8(pc++));
			WriteMemory8(ltmp,B);
			cycles += 19;
			break;
		case 0x71:	//ld (ix+d),c
			ltmp = (unsigned long)(unsigned short)((signed short)ix + (signed char)ReadMemory8(pc++));
			WriteMemory8(ltmp,C);
			cycles += 19;
			break;
		case 0x72:	//ld (ix+d),d
			ltmp = (unsigned long)(unsigned short)((signed short)ix + (signed char)ReadMemory8(pc++));
			WriteMemory8(ltmp,D);
			cycles += 19;
			break;
		case 0x73:	//ld (ix+d),e
			ltmp = (unsigned long)(unsigned short)((signed short)ix + (signed char)ReadMemory8(pc++));
			WriteMemory8(ltmp,E);
			cycles += 19;
			break;
		case 0x74:	//ld (ix+d),h
			ltmp = (unsigned long)(unsigned short)((signed short)ix + (signed char)ReadMemory8(pc++));
			WriteMemory8(ltmp,H);
			cycles += 19;
			break;
		case 0x75:	//ld (ix+d),l
			ltmp = (unsigned long)(unsigned short)((signed short)ix + (signed char)ReadMemory8(pc++));
			WriteMemory8(ltmp,L);
			cycles += 19;
			break;

		case 0x77:	//ld (ix+d),a
			ltmp = (unsigned long)(unsigned short)((signed short)ix + (signed char)ReadMemory8(pc++));
			WriteMemory8(ltmp,A);
			cycles += 19;
			break;
		case 0x7E:	//ld a,(ix+d)
			ltmp = (unsigned long)(unsigned short)((signed short)ix + (signed char)ReadMemory8(pc++));
			A = ReadMemory8(ltmp);
			cycles += 19;
			break;
		case 0xCB:	return(ExecuteOpcodeDDCB());
		case 0xE1:	//pop ix
			POP16(ix);
			break;
		case 0xE5:	//push ix
			PUSH16(ix);
			cycles += 11;
			break;
		default:
			printf("bad DD opcode $%02X\n",opcode);
			return(1);
	}
	return(0);
}

int CDeadZ80::ExecuteOpcodeED()
{
	unsigned char opcode = ReadMemory8(pc++);
	unsigned short stmp,tmp16;
	unsigned char tmp;
	unsigned long ltmp;

	switch(opcode) {
		case 0x43:	//ld (nn),bc
			WriteMemory16(ReadMemory16(pc),BC);
			pc += 2;
			cycles += 14;
			break;
		case 0x4B:	//ld bc,(nn)
			BC = ReadMemory16(ReadMemory16(pc));
			pc += 2;
			cycles += 14;
			break;
		case 0x56:	//im 1
			intmode = 1;
			cycles += 8;
			break;
		case 0x5A:	ADD16(HL,DE);		cycles += 10;	break;

		case 0x5B:	//ld de,(nn)
			DE = ReadMemory16(ReadMemory16(pc));
			pc += 2;
			cycles += 14;
			break;
			
		case 0x6A:	ADD16(HL,HL);		cycles += 15;	break;

		case 0x6B:	//ld hl,(nn)
			HL = ReadMemory16(ReadMemory16(pc));
			pc += 2;
			cycles += 14;
			break;

		case 0xB0:	//ldir
			tmp = ReadMemory8(HL);
			WriteMemory8(DE,tmp);
			DE++;
			HL++;
			BC--;
			if(BC != 0) {
				pc -= 2;
				cycles += 21;
				F &= ~(FLAG_N | FLAG_H | 0x28);
				F |= FLAG_P;
			}
			else {
				F &= ~(FLAG_H | FLAG_P | FLAG_N | 0x28);
				cycles += 16;
			}
		//	printf("ldir done: pc = $%04X\n",pc);
			tmp += A;
			F |= tmp & 8;
			F |= (tmp & 2) << 4;
			break;
		default:
			printf("bad ED opcode $%02X\n",opcode);
			return(1);
	}
	return(0);
}

int CDeadZ80::ExecuteOpcodeFD()
{
	unsigned char opcode = ReadMemory8(pc++);
	unsigned short stmp,tmp16;
	unsigned char tmp;
	unsigned long ltmp;

	switch(opcode) {
		case 0x21:	//ld iy,nn
			iy = ReadMemory16(pc);
			pc += 2;
			cycles += 14;
			break;
		case 0x22:	//ld (nn),iy
			WriteMemory16(ReadMemory16(pc),iy);
			pc += 2;
			cycles += 14;
			break;
		case 0x23:	//inc iy
			iy++;
			cycles += 10;
			break;

		case 0x2A:	//ld iy,(nn)
			iy = ReadMemory16(ReadMemory16(pc));
			pc += 2;
			cycles += 14;
			break;
		case 0x36:	//ld (iy+d),n
			ltmp = (unsigned long)(unsigned short)((signed short)iy + (signed char)ReadMemory8(pc++));
			WriteMemory8(ltmp,ReadMemory8(pc++));
			cycles += 19;
			break;


		case 0xE1:	//pop iy
			POP16(iy);
			break;
		case 0xE5:	//push iy
			PUSH16(iy);
			break;

		default:
			printf("bad FD opcode $%02X\n",opcode);
			return(1);
	}
	return(0);
}

/*
 * execute one opcode
 *
 * reads opcode from current pc, then does its operation
 */
int CDeadZ80::Step()
{
	unsigned char tmp;
	unsigned short stmp,utmp[3];
	unsigned long ltmp;

	if(inside_irq) {
		opcode = irqfunc(user);
		inside_irq = 0;
	}
	else
		//fetch opcode from memory
		opcode = ReadMemory8(pc++);

	if(halt)
		return(0);

	//do operation of opcode
	switch(opcode) {

		case 0x00:							cycles += 4;	break;

		case 0x01:	//ld bc,imm16
			BC = ReadMemory16(pc);
			pc += 2;
			cycles += 10;
			break;

		case 0x02:	//ld (bc),a
			WriteMemory8(BC,A);
			cycles += 7;
			break;

		case 0x03:	INC16(BC);				cycles += 6;	break;
		case 0x04:	INC(B);					cycles += 4;	break;
		case 0x05:	DEC(B);					cycles += 4;	break;
		case 0x06:	B = ReadMemory8(pc++);	cycles += 7;	break;

		case 0x07:	//rlca
			tmp = (A & 0x80) >> 7;
			A <<= 1;
			A |= tmp & 1;
			F &= ~(FLAG_N | FLAG_H | FLAG_C | 0x28);
			F |= tmp | (A & 0x28);
			break;

		case 0x08:	//ex af,af'
			utmp[0] = regs->af.word;
			regs->af.word = alt.af.word;
			alt.af.word = utmp[0];
			cycles += 4;
			break;

		case 0x09:	//add hl,bc
			ADD16(HL,BC);
			break;

			case 0x0A:	//ld a,(bc)
			A = ReadMemory8(BC);
			break;

		case 0x0B:	DEC16(BC);				cycles += 6;	break;
		case 0x0C:	INC(C);					cycles += 4;	break;
		case 0x0D:	DEC(C);					cycles += 4;	break;
		case 0x0E:	C = ReadMemory8(pc++);	cycles += 7;	break;

		case 0x0F:	//rrca
			F = (F & (FLAG_P | FLAG_Z | FLAG_S)) | (A & 1);
			A = (A >> 1) | ((A << 7) & 0x80);
			F |= A & 0x28;
			break;

		case 0x10:	//djnz imm8
			stmp = (signed char)ReadMemory8(pc++) + pc;
			if(--B > 0) {
				pc = stmp;
				cycles += 13;
			}
			else
				cycles += 8;
			break;

		case 0x11:	//ld de,imm16
			DE = ReadMemory16(pc);
			pc += 2;
			cycles += 10;
			break;

		case 0x12:	//ld (de),a
			WriteMemory8(DE,A);
			cycles += 7;
			break;

		case 0x13:	INC16(DE);				cycles += 6;	break;
		case 0x14:	INC(D);					cycles += 4;	break;
		case 0x15:	DEC(D);					cycles += 4;	break;
		case 0x16:	D = ReadMemory8(pc++);	cycles += 7;	break;

		case 0x18:	//jr simm8
			stmp = (signed char)ReadMemory8(pc++) + pc;
			pc = stmp;
			cycles += 13;
			break;

		case 0x19:	//add hl,de
			ADD16(HL,DE);
			break;

		case 0x1A:	A = ReadMemory8(DE);	cycles += 7;	break;
		case 0x1B:	DEC16(DE);				cycles += 6;	break;
		case 0x1C:	INC(E);					cycles += 4;	break;
		case 0x1D:	DEC(E);					cycles += 4;	break;
		case 0x1E:	E = ReadMemory8(pc++);	cycles += 7;	break;

		case 0x1F:	//rra
			tmp = A & 1;
			A >>= 1;
			A |= (F << 7) & 0x80;
			F &= ~(FLAG_N | FLAG_H | FLAG_C | 0x28);
			F |= tmp | (A & 0x28);
			break;

		case 0x20:	//jr nz,simm8
			stmp = (signed char)ReadMemory8(pc++) + pc;
			if((F & FLAG_Z) == 0) {
				pc = stmp;
				cycles += 13;
			}
			else
				cycles += 8;
			break;

		case 0x21:	//ld hl,imm16
			HL = ReadMemory16(pc);
			pc += 2;
			cycles += 10;
			break;

		case 0x22:	//ld (u16),hl
			WriteMemory16(ReadMemory16(pc),HL);
			pc += 2;
			cycles += 13;
			break;

		case 0x23:	INC16(HL);				cycles += 6;	break;
		case 0x24:	INC(H);					cycles += 4;	break;
		case 0x25:	DEC(H);					cycles += 4;	break;
		case 0x26:	H = ReadMemory8(pc++);	cycles += 7;	break;

		case 0x27:	//daa
			DAA;
			break;

		case 0x28:	//jr z,simm8
			stmp = (signed char)ReadMemory8(pc++) + pc;
			if((F & FLAG_Z) != 0) {
				pc = stmp;
				cycles += 13;
			}
			else
				cycles += 8;
			break;

		case 0x29:	ADD16(HL,HL);	cycles += 6;	break;

		case 0x2A:	//ld hl,(imm16)
			HL = ReadMemory16(ReadMemory16(pc));
			pc += 2;
			cycles += 10;
			break;

		case 0x2B:	DEC16(HL);		cycles += 6;	break;
		case 0x2C:	INC(L);			cycles += 4;	break;
		case 0x2D:	DEC(L);			cycles += 4;	break;
		case 0x2E:	L = ReadMemory8(pc++);	cycles += 7;	break;

		case 0x2F:	//cpl
			A ^= 0xFF;
			F |= FLAG_N | FLAG_H | 0x28;
			break;

		case 0x30:	//jr nc,simm8
			stmp = (signed char)ReadMemory8(pc++) + pc;
			if((F & FLAG_C) == 0) {
				pc = stmp;
				cycles += 13;
			}
			else
				cycles += 8;
			break;

		case 0x31:	//ld sp,nnnn
			sp = ReadMemory16(pc);
			pc += 2;
			cycles += 20;
			break;

		case 0x32:	//ld (u16),a
			WriteMemory8(ReadMemory16(pc),A);
			pc += 2;
			cycles += 13;
			break;

		case 0x33:	INC16(sp);		cycles += 7;		break;

		case 0x34:	//inc (hl)
			tmp = ReadMemory8(HL);
			stmp = tmp + 1;
			WriteMemory8(HL,stmp);
			F &= ~(FLAG_S | FLAG_Z | FLAG_V | FLAG_N | FLAG_H | 0x28);
			F |= stmp & 0x28;
			checkSZ(stmp & 0xFF);
			checkV(tmp,1,stmp);
			if((tmp & 8) && (1 & 8))
				F |= FLAG_H;
			cycles += 4;
			break;

		case 0x35:	//dec (hl)
			tmp = ReadMemory8(HL);
			DEC(tmp);
			WriteMemory8(HL,tmp);
			cycles += 7;
			break;

		case 0x36:	//ld (hl),n
			WriteMemory8(HL,ReadMemory8(pc++));
			cycles += 7;
			break;

		case 0x37:
			F |= FLAG_C;
			break;

		case 0x38:	//jr c,simm8
			stmp = (signed char)ReadMemory8(pc++) + pc;
			if((F & FLAG_C) != 0) {
				pc = stmp;
				cycles += 13;
			}
			else
				cycles += 8;
			break;

		case 0x39:	//add hl,sp
			ADD16(HL,sp);
			cycles += 7;
			break;

		case 0x3A:	//ld a,(nn)
			A = ReadMemory8(ReadMemory16(pc));
			pc += 2;
			cycles += 10;
			break;

		case 0x3B:	DEC16(sp);							cycles += 6;	break;
		case 0x3C:	INC(A);								cycles += 4;	break;
		case 0x3D:	DEC(A);								cycles += 4;	break;
		case 0x3E:	A = ReadMemory8(pc++);				cycles += 7;	break;

		case 0x3F:	//ccf
			F &= FLAG_P | FLAG_Z | FLAG_S;
			F |= (F & FLAG_C) ? FLAG_H : FLAG_C;
			F |= A & 0x28;
			break;

		case 0x40:	B = B;								cycles += 4;	break;
		case 0x41:	B = C;								cycles += 4;	break;
		case 0x42:	B = D;								cycles += 4;	break;
		case 0x43:	B = E;								cycles += 4;	break;
		case 0x44:	B = H;								cycles += 4;	break;
		case 0x45:	B = L;								cycles += 4;	break;
		case 0x46:	B = ReadMemory8(HL);				cycles += 7;	break;
		case 0x47:	B = A;								cycles += 4;	break;
		case 0x48:	C = B;								cycles += 4;	break;
		case 0x49:	C = C;								cycles += 4;	break;
		case 0x4A:	C = D;								cycles += 4;	break;
		case 0x4B:	C = E;								cycles += 4;	break;
		case 0x4C:	C = H;								cycles += 4;	break;
		case 0x4D:	C = L;								cycles += 4;	break;
		case 0x4E:	C = ReadMemory8(HL);				cycles += 7;	break;
		case 0x4F:	C = A;								cycles += 4;	break;
		case 0x50:	D = B;								cycles += 4;	break;
		case 0x51:	D = C;								cycles += 4;	break;
		case 0x52:	D = D;								cycles += 4;	break;
		case 0x53:	D = E;								cycles += 4;	break;
		case 0x54:	D = H;								cycles += 4;	break;
		case 0x55:	D = L;								cycles += 4;	break;
		case 0x56:	D = ReadMemory8(HL);				cycles += 7;	break;
		case 0x57:	D = A;								cycles += 4;	break;
		case 0x58:	E = B;								cycles += 4;	break;
		case 0x59:	E = C;								cycles += 4;	break;
		case 0x5A:	E = D;								cycles += 4;	break;
		case 0x5B:	E = E;								cycles += 4;	break;
		case 0x5C:	E = H;								cycles += 4;	break;
		case 0x5D:	E = L;								cycles += 4;	break;
		case 0x5E:	E = ReadMemory8(HL);				cycles += 7;	break;
		case 0x5F:	E = A;								cycles += 4;	break;
		case 0x60:	H = B;								cycles += 4;	break;
		case 0x61:	H = C;								cycles += 4;	break;
		case 0x62:	H = D;								cycles += 4;	break;
		case 0x63:	H = E;								cycles += 4;	break;
		case 0x64:	H = H;								cycles += 4;	break;
		case 0x65:	H = L;								cycles += 4;	break;
		case 0x66:	H = ReadMemory8(HL);				cycles += 7;	break;
		case 0x67:	H = A;								cycles += 4;	break;
		case 0x68:	L = B;								cycles += 4;	break;
		case 0x69:	L = C;								cycles += 4;	break;
		case 0x6A:	L = D;								cycles += 4;	break;
		case 0x6B:	L = E;								cycles += 4;	break;
		case 0x6C:	L = H;								cycles += 4;	break;
		case 0x6D:	L = L;								cycles += 4;	break;
		case 0x6E:	L = ReadMemory8(HL);				cycles += 7;	break;
		case 0x6F:	L = A;								cycles += 4;	break;
		case 0x70:	WriteMemory8(HL,B);					cycles += 7;	break;
		case 0x71:	WriteMemory8(HL,C);					cycles += 7;	break;
		case 0x72:	WriteMemory8(HL,D);					cycles += 7;	break;
		case 0x73:	WriteMemory8(HL,E);					cycles += 7;	break;
		case 0x74:	WriteMemory8(HL,H);					cycles += 7;	break;
		case 0x75:	WriteMemory8(HL,L);					cycles += 7;	break;
		case 0x76:	halt = 1;	pc--;					cycles += 2;	break;
		case 0x77:	WriteMemory8(HL,A);					cycles += 7;	break;
		case 0x78:	A = B;								cycles += 4;	break;
		case 0x79:	A = C;								cycles += 4;	break;
		case 0x7A:	A = D;								cycles += 4;	break;
		case 0x7B:	A = E;								cycles += 4;	break;
		case 0x7C:	A = H;								cycles += 4;	break;
		case 0x7D:	A = L;								cycles += 4;	break;
		case 0x7E:	A = ReadMemory8(HL);				cycles += 7;	break;
		case 0x7F:	A = A;								cycles += 4;	break;
		case 0x80:	ADD(B);								cycles += 4;	break;
		case 0x81:	ADD(C);								cycles += 4;	break;
		case 0x82:	ADD(D);								cycles += 4;	break;
		case 0x83:	ADD(E);								cycles += 4;	break;
		case 0x84:	ADD(H);								cycles += 4;	break;
		case 0x85:	ADD(L);								cycles += 4;	break;
		case 0x86:	tmp = ReadMemory8(HL); ADD(tmp);	cycles += 7;	break;
		case 0x87:	ADD(A);								cycles += 4;	break;
		case 0x88:	ADC(B);								cycles += 4;	break;
		case 0x89:	ADC(C);								cycles += 4;	break;
		case 0x8A:	ADC(D);								cycles += 4;	break;
		case 0x8B:	ADC(E);								cycles += 4;	break;
		case 0x8C:	ADC(H);								cycles += 4;	break;
		case 0x8D:	ADC(L);								cycles += 4;	break;
		case 0x8E:	tmp = ReadMemory8(HL); ADC(tmp);	cycles += 7;	break;
		case 0x8F:	ADC(A);								cycles += 4;	break;
		case 0x90:	SUB(B);								cycles += 4;	break;
		case 0x91:	SUB(C);								cycles += 4;	break;
		case 0x92:	SUB(D);								cycles += 4;	break;
		case 0x93:	SUB(E);								cycles += 4;	break;
		case 0x94:	SUB(H);								cycles += 4;	break;
		case 0x95:	SUB(L);								cycles += 4;	break;
		case 0x96:	tmp = ReadMemory8(HL); SUB(tmp);	cycles += 7;	break;
		case 0x97:	SUB(A);								cycles += 4;	break;
/*		case 0x98:	SBC(B);								cycles += 4;	break;
		case 0x99:	SBC(C);								cycles += 4;	break;
		case 0x9A:	SBC(D);								cycles += 4;	break;
		case 0x9B:	SBC(E);								cycles += 4;	break;
		case 0x9C:	SBC(H);								cycles += 4;	break;
		case 0x9D:	SBC(L);								cycles += 4;	break;
		case 0x9E:	tmp = ReadMemory8(HL); SBC(tmp);	cycles += 7;	break;
		case 0x9F:	SBC(A);								cycles += 4;	break;
*/		case 0xA0:	AND(B);								cycles += 4;	break;
		case 0xA1:	AND(C);								cycles += 4;	break;
		case 0xA2:	AND(D);								cycles += 4;	break;
		case 0xA3:	AND(E);								cycles += 4;	break;
		case 0xA4:	AND(H);								cycles += 4;	break;
		case 0xA5:	AND(L);								cycles += 4;	break;
		case 0xA6:	tmp = ReadMemory8(HL); AND(tmp);	cycles += 7;	break;
		case 0xA7:	AND(A);								cycles += 4;	break;
		case 0xA8:	XOR(B);								cycles += 4;	break;
		case 0xA9:	XOR(C);								cycles += 4;	break;
		case 0xAA:	XOR(D);								cycles += 4;	break;
		case 0xAB:	XOR(E);								cycles += 4;	break;
		case 0xAC:	XOR(H);								cycles += 4;	break;
		case 0xAD:	XOR(L);								cycles += 4;	break;
		case 0xAE:	tmp = ReadMemory8(HL); XOR(tmp);			cycles += 7;	break;
		case 0xAF:	XOR(A);										cycles += 4;	break;
		case 0xB0:	OR(B);										cycles += 4;	break;
		case 0xB1:	OR(C);										cycles += 4;	break;
		case 0xB2:	OR(D);										cycles += 4;	break;
		case 0xB3:	OR(E);										cycles += 4;	break;
		case 0xB4:	OR(H);										cycles += 4;	break;
		case 0xB5:	OR(L);										cycles += 4;	break;
		case 0xB6:	tmp = ReadMemory8(HL); OR(tmp);			cycles += 7;	break;
		case 0xB7:	OR(A);										cycles += 4;	break;
		case 0xB8:	CP(B);										cycles += 4;	break;
		case 0xB9:	CP(C);										cycles += 4;	break;
		case 0xBA:	CP(D);										cycles += 4;	break;
		case 0xBB:	CP(E);										cycles += 4;	break;
		case 0xBC:	CP(H);										cycles += 4;	break;
		case 0xBD:	CP(L);										cycles += 4;	break;
		case 0xBE:	tmp = ReadMemory8(HL); CP(tmp);			cycles += 7;	break;
		case 0xBF:	CP(A);										cycles += 4;	break;
		case 0xC0:	RET((F & FLAG_Z) == 0);											break;
		case 0xC1:	POP16(BC);									cycles += 10;	break;
		case 0xC2:	JR((F & FLAG_Z) == 0);											break;
		case 0xC3:	JP(ReadMemory16(pc));				cycles += 0;	break;
		case 0xC4:	CALL((F & FLAG_Z) == 0);										break;
		case 0xC5:	PUSH16(BC);									cycles += 11;	break;
		case 0xC6:	tmp = ReadMemory8(pc++);ADD(tmp);	cycles += 4;	break;
		case 0xC7:	RST(0x00);														break;
		case 0xC8:	RET((F & FLAG_Z) != 0);											break;
		case 0xC9:	RET(1);															break;
		case 0xCA:	JR((F & FLAG_Z) != 0);											break;
		case 0xCB:	return(ExecuteOpcodeCB());
		case 0xCC:	CALL((F & FLAG_Z) != 0);										break;
		case 0xCD:	CALL(1);														break;
		case 0xCE:	tmp = ReadMemory8(pc++); ADC(tmp);	cycles += 7;	break;
		case 0xCF:	RST(0x08);														break;
		case 0xD0:	RET((F & FLAG_C) == 0);											break;
		case 0xD1:	POP16(DE);									cycles += 10;	break;
		case 0xD2:	JR((F & FLAG_C) == 0);											break;

		case 0xD4:	CALL((F & FLAG_C) == 0);										break;
		case 0xD5:	PUSH16(DE);									cycles += 11;	break;
		case 0xD6:	SUB(ReadMemory8(pc++));				cycles += 14;	break;
		case 0xD7:	RST(0x10);														break;
		case 0xD8:	RET((F & FLAG_C) != 0);											break;
		case 0xD9:	EXX();															break;
		case 0xDA:	JR((F & FLAG_C) != 0);											break;

		case 0xDC:	CALL((F & FLAG_C) != 0);										break;
		case 0xDD:	return(ExecuteOpcodeDD());

		case 0xDF:	RST(0x18);														break;
		case 0xE0:	RET((F & FLAG_P) == 0);											break;
		case 0xE1:	POP16(HL);									cycles += 10;	break;
		case 0xE2:	JR((F & FLAG_P) == 0);											break;

		case 0xE4:	CALL((F & FLAG_P) == 0);										break;
		case 0xE5:	PUSH16(HL);									cycles += 11;	break;
		case 0xE6:	AND(ReadMemory8(pc++));				cycles += 7;	break;
		case 0xE7:	RST(0x20);														break;
		case 0xE8:	RET((F & FLAG_P) != 0);											break;
		case 0xE9:	JP(HL);															break;
		case 0xEA:	JR((F & FLAG_P) != 0);											break;
		case 0xEB:	EX(DE,HL);														break;
		case 0xEC:	CALL((F & FLAG_P) != 0);										break;
		case 0xED:	return(ExecuteOpcodeED());
		case 0xEE:	XOR(ReadMemory8(pc++));				cycles += 7;	break;
		case 0xEF:	RST(0x28);														break;
		case 0xF0:	RET((F & FLAG_S) == 0);											break;
		case 0xF1:	POP16(AF);									cycles += 10;	break;
		case 0xF2:	JR((F & FLAG_S) == 0);											break;
		case 0xF3:	iff1 = iff2 = 0;					cycles += 4;	break;
		case 0xF4:	CALL((F & FLAG_S) == 0);										break;
		case 0xF5:	PUSH16(AF);														break;
		case 0xF6:	OR(ReadMemory8(pc++));				cycles += 7;	break;
		case 0xF7:	RST(0x30);														break;
		case 0xF8:	RET((F & FLAG_S) != 0);											break;
		case 0xF9:	sp = HL;													break;
		case 0xFA:	JR((F & FLAG_S) != 0);											break;
		case 0xFB:	iff1 = iff2 = 1;					cycles += 4;	break;
		case 0xFC:	CALL((F & FLAG_S) != 0);										break;
		case 0xFD:	return(ExecuteOpcodeFD());
		case 0xFE:	tmp = ReadMemory8(pc++);CP(tmp);	cycles += 7;	break;
		case 0xFF:	RST(0x38);														break;

		default:	//bad opcode
			printf("bad opcode = $%02X\n",opcode);
			return(1);

	}
	return(0);
}





















CDeadZ80::CDeadZ80()
{
}

CDeadZ80::~CDeadZ80()
{
}

void CDeadZ80::Init()
{
	int i;
	
	for(i=0;i<Z80_PAGE_NUM;i++) {
		readpages[i] = writepages[i] = 0;
	}
}

void CDeadZ80::Reset()
{
	cycles = 0;			//reset cycle counter
	halt = 0;				//clear halt flag
	intmode = 0;
	inside_irq = 0;

	regs = &alt;
	AF = 0xFFFF;
	BC = 0xFFFF;
	DE = 0xFFFF;
	HL = 0xFFFF;

	regs = &main;
	AF = 0xFFFF;
	BC = 0xFFFF;
	DE = 0xFFFF;
	HL = 0xFFFF;

	sp = 0xFFFF;

	pc = 0;				//reset pc
}

void CDeadZ80::NMI()
{
	iff2 = iff1;
	iff1 = 0;
	WriteMemory8(--sp,(pc >> 8) & 0xFF);
	WriteMemory8(--sp,pc & 0xFF);
	pc = 0x0066;
	cycles += 11;
}

void CDeadZ80::IRQ()
{
	if(iff1 == 0)
		return;

	if(halt) {
		halt = 0;
		pc++;
	}

	switch(intmode) {
		case 0:
			inside_irq = 1;
			Step();
			break;
		case 1:
			WriteMemory8(--sp,(pc >> 8) & 0xFF);
			WriteMemory8(--sp,(pc >> 0) & 0xFF);
			pc = 0x0038;
			cycles += 13;
			break;
		case 2:
			printf("im 2 not done\n");
			break;
		default:
			printf("bad im\n");
			break;
	}
}

u32 CDeadZ80::Execute(u32 c)
{
	unsigned long start = cycles;
	unsigned long end = cycles + c;

	while(cycles < end) {
		if(Step() > 0)
			return(BAD_OPCODE);
	}
	return(end - start);
}



//step function goes here



unsigned char CDeadZ80::ReadMemory8(unsigned long addr)
{
//	printf("reading from $%04X\n",addr);
	if(readpages[addr >> Z80_PAGE_SHIFT])
		return(readpages[addr >> Z80_PAGE_SHIFT][addr & Z80_PAGE_MASK]);
	return(readfunc(user,addr));
}

unsigned short CDeadZ80::ReadMemory16(unsigned long addr)
{
	return(ReadMemory8(addr) | (ReadMemory8(addr+1) << 8));
}

void CDeadZ80::WriteMemory8(unsigned long addr,unsigned char data)
{
//	printf("writing to $%04X = $%02X\n",addr,data);
	if(writepages[addr >> Z80_PAGE_SHIFT])
		writepages[addr >> Z80_PAGE_SHIFT][addr & Z80_PAGE_MASK] = data;
	else
		writefunc(user,addr,data);
}

void CDeadZ80::WriteMemory16(unsigned long addr,unsigned short data)
{
	WriteMemory8(addr,data & 0xFF);
	WriteMemory8(addr+1,(data >> 8) & 0xFF);
}

u32 CDeadZ80::Disassemble(char *dest,u32 p)
{
sprintf(dest,"$%04X:",p);
p++;
return(p);
}

char *CDeadZ80::GenerateRegNames(char *dest)
{
*dest = 0;
return(dest);
}

char *CDeadZ80::GenerateRegData(char *dest)
{
*dest = 0;
return(dest);
}

u32 CDeadZ80::GetPC()
{
	return(pc);
}

u32 CDeadZ80::GetCycle()
{
	return(cycles);
}

void CDeadZ80::SetRead(ReadFunc *r)
{
	readfunc = r;
}

void CDeadZ80::SetWrite(WriteFunc *w)
{
	writefunc = w;
}

void CDeadZ80::SetIRQ(IRQFunc *i)
{
	irqfunc = i;
}

void CDeadZ80::SetUser(void *u)
{
	user = u;
}

void CDeadZ80::SetReadPage(int p,u8 *d)
{
	readpages[p] = d;
}

void CDeadZ80::SetWritePage(int p,u8 *d)
{
	writepages[p] = d;
}

void CDeadZ80::SetPage(int p,u8 *d)
{
	SetReadPage(p,d);
	SetWritePage(p,d);
}
